<template>
  <div style="display: flex; height: 100%; flex: 1;">
    <HierarchyList :pagination="pagination" :columns="columns" :load-data="loadData"
                   ref="refHiMenu" :search-form="searchForms" :create-label="'新增菜单'"
                   :add-item="addMenu" :hidePageable="true"/>
    <EditDialog ref="refEditDlg" :columns="columns" :rules="rules" :submit="onSubmit"
                :form-label-width="100" :is-show-dialog="false"/>
  </div>
</template>

<script setup lang="ts">

import {nextTick, reactive, ref} from "vue";
import {currentNames, TYPES} from "@/stores/conf";
import {loadAssetLevel} from "@/apis";
import HierarchyList from "@/widget/list/HierarchyList.vue";
import {msgError, msgInfo, showInfo} from "@/utils/InfoUtil";
import EditDialog from "@/components/common/EditDialog.vue";
import {computeTreeData, findTreeParent} from "@/utils/DataTreeUtil";
import {buildAsset} from "@/utils/DataUtil";
import {useCurrent} from "@/utils/UseCurrentFunc";
import {handleLevelMenus} from "@/utils/SystemUtil";
import {useStore} from "@/stores";
import {useAssetOp} from "@/utils/UseAssetOp";

const props = withDefaults(defineProps<{
  entry: any,
}>(), {});

const store = useStore();
const refEditDlg = ref();
const refHiMenu = ref();
const currentItem = ref<any>();
const menuData = ref([]);

const {updateCurrent, current} = useCurrent(currentNames.MENU);
const {doSaveAsset, doDeleteAsset} = useAssetOp(props.entry);

const rules = reactive({
  name: [{required: true, message: '请输入菜单名称', trigger: ['blur']},],
})

const getSearchItems = () => {
  const searchItems = [];
  const productType = {
    type: 'select',
    name: 'productCode',
    label: `产品类型`,
    size: 'default',
    placeholder: `请选择产品类型`,
    clearable: true,
    defValue: '',
    minWidth: '160px',
  };

  // searchItems.push(productType);
  searchItems.push({
    type: 'input',
    name: 'name',
    label: `菜单名称`,
    size: 'default',
    placeholder: `请输入菜单名称`,
    clearable: true,
    defValue: '',
  });

  return searchItems;
}

const searchForms = ref(getSearchItems());

const loadData = async (params: any) => {
  const platform: any = store.getCurrentPlatform();

  const result = await loadAssetLevel({
    server: props.entry.server,
    targetId: platform.id,
    assetType: TYPES.MENU,
    ...params,
  });

  if (result && result.data) {
    menuData.value = [];
    handleLevelMenus(menuData.value, result.data, menuProps);
    delete result.data;
    result.data = {};
    result.data.data = menuData.value;
  } else {
    menuData.value = [];
  }

  return result;
}

const refresh = () => {
  refHiMenu.value?.refresh(current())
}

const checkSubmit = (item: Record<string, any>, editType: string) => {
  if ('add' !== editType) {
    const parent: MenuType | undefined = findTreeParent(menuData.value, item);
    if (parent) {
      if (item.menuType === 2 && parent.menuType !== 1) {
        msgError('按钮类型菜单项父菜单类型错误');
        return false;
      } else if (item.menuType === 1 && parent.menuType !== 0) {
        msgError('菜单项父菜单类型错误');
        return false;
      } else if (item.menuType === 0 && parent.menuType !== 0) {
        msgError('目录类型菜单项父菜单类型错误');
        return false;
      }
    }
  }
  return true;
}

const menuProps: any = [
  'icon',
  'openMode',
  'hidden',
  'routeName',
  'routePath',
  'level',
  'component',
  'menuType',
  'keepAlive'
]

const onSubmit = async (item: Record<string, any>, editType: string) => {
  const platform: any = store.getCurrentPlatform();
  let assetInfo = buildAsset(item, 'MENU', {
    icon: item.menuIcon || item.icon,
    openMode: item.openMode,
    hidden: item.hidden,
    routeName: item.routeName,
    routePath: item.routePath,
    level: item.level,
    component: item.component,
    menuType: item.menuType,
    keepAlive: item.keepAlive,
  });

  assetInfo.classify = "TREE";

  if (checkSubmit(item, editType)) {
    const result = await doSaveAsset(platform.id, assetInfo);

    if (result.code === 0) {
      msgInfo('保存菜单成功！');
      setTimeout(() => refresh(),300);
    } else {
      msgError(result.message);
    }

    return result;
  }
}

const handleMenuTypeChanged = (cols: any, val: any) => {
  let canEdit: boolean = true;
  if (val == 2) {
    canEdit = false;
  }
  cols[4].canEdit = canEdit;
  cols[5].canEdit = canEdit;
  cols[6].canEdit = val == 1 || val == 0;
  cols[7].canEdit = val == 1;
  cols[9].canEdit = canEdit;
  cols[10].canEdit = canEdit;
}

const getMenuTypeOptions = (isAdd: any) => {
  let options: any = [
    {
      value: 0,
      label: '目录'
    },
    {
      value: 1,
      label: '菜单'
    },
  ];
  if (!isAdd) {
    options.push({
      value: 2,
      label: '按钮'
    });
  }
  return options;
}

const newMenu = () => {
  return {
    state: 1,
    hidden: 0,
    level: 1,
    openMode: 1,
    menuType: 1,
    keepAlive: 1,
    type: TYPES.MENU,
  };
}

const pagination = ref({
  current: 1,
  pageSize: 20,
  total: 0,
});

const getTargetId = () => {
  return '';
}

const columns = ref([
  {
    id: 'id',
    name: '菜单标识',
    hideCol: true,
    show: false,
    canEdit: false,
  },
  {
    id: 'parentId',
    name: '父菜单',
    type: 'tree',
    show: false,
    canEdit: true,
    readOnly: true,
    treeKey: 'parentName'
  },
  {
    id: 'name',
    name: '菜单名称',
    sort: 'custom',
    show: true,
    filterMethod: (value: string, row: any) => {

    },
    action: (data: any, row: any, index: number) => {
      updateCurrent({type: TYPES.MENU, ...row})
    }
  },
  {
    id: 'menuType',
    name: '菜单类型',
    show: true,
    tag: 'true',
    type: 'select',
    tagText: (tag: number) => {
      return tag === 0 ? "目录" : tag === 1 ? "菜单" : '按钮';
    },
    selectChanged: (editCols: any, val: any) => {
      handleMenuTypeChanged(editCols, val);
    },
    options: [
      {
        value: 0,
        label: '目录'
      },
      {
        value: 1,
        label: '菜单'
      },
      {
        value: 2,
        label: '按钮'
      }
    ]
  },
  {
    id: 'component',
    name: '组件地址',
    show: false,
  },
  {
    id: 'routeName',
    name: '路由名称',
    show: false,
  },
  {
    id: 'routePath',
    name: '路由地址',
    show: false,
  },
  {
    id: 'openMode',
    name: '打开方式',
    show: true,
    tag: 'true',
    type: 'select',
    tagStyle: (tag: number) => {
      return tag === 0 ? {'color': 'green'} : {'color': 'blue'};
    },
    tagText: (tag: number) => {
      return tag === 0 ? "新窗口" : '本页';
    },
    options: [
      {
        value: 1,
        label: '本页'
      },
      {
        value: 0,
        label: '新窗口'
      }
    ]
  },
  {
    id: 'code',
    name: '菜单编码',
    show: true,
    inputCheck: (row: any) => {
      row.code = row.code.replace(/[^\w\.\/:=|<>+-_%&*#()]/ig,'');
      if (row.code.length > 31) {
        row.code = row.code.substring(0, 31);
      }
    }
  },
  {
    id: 'hidden',
    name: '是否可见',
    show: true,
    tag: 'true',
    type: 'select',
    tagType: (tag: number) => {
      return tag === 1 ? 'success' : 'danger';
    },
    tagText: (tag: number) => {
      return tag === 1 ? "隐藏" : '可见';
    },
    options: [
      {
        value: 0,
        label: '可见'
      },
      {
        value: 1,
        label: '隐藏'
      }
    ]
  },
  {
    id: 'level',
    name: '顺序',
    show: true,
  },
  {
    id: 'icon',
    name: '菜单图标',
    show: true,
    type: 'icon',
  },
  {
    id: 'keepAlive',
    name: '缓存状态',
    show: true,
    tag: 'true',
    type: 'select',
    tagType: (tag: number) => {
      return tag === 1 ? 'success' : 'danger';
    },
    tagText: (tag: number) => {
      return tag === 1 ? '缓存' : '未缓存';
    },
    options: [
      {
        value: 1,
        label: '缓存'
      },
      {
        value: 0,
        label: '未缓存'
      }
    ]
  },
  {
    id: 'operation',
    name: '操作',
    show: true,
    hideCol: true,
    canEdit: false,
    fixed: 'right',
    operations: [
      {
        name: '新增',
        disabled: (row: any): boolean => {
          return row.menuType === 2;
        },
        callback: (data: any, row: any, index: number): void => {
          const parent = row;

          if (parent.menuType === 0 || parent.menuType === 1) {
            currentItem.value = newMenu();
            currentItem.value.disabled = true;
            currentItem.value.parentId = parent.id;
            currentItem.value.treeData = [
              {
                value: parent.id,
                label: parent.name,
              }
            ]

            if (parent.menuType === 0) {
              currentItem.value.menuType = 1;
              columns.value[3].readOnly = false;
              columns.value[3].options = getMenuTypeOptions(true);
            } else {
              currentItem.value.menuType = 2;
              columns.value[3].readOnly = false;
              columns.value[3].options = getMenuTypeOptions(false);
              columns.value[3].options.shift();
            }

            handleMenuTypeChanged(columns.value, currentItem.value.menuType);

            refEditDlg.value?.editAdd('新增菜单', currentItem.value);
          } else {
            console.log('---- 当前菜单不是类型错误:', parent.menuType);
          }
        }
      },
      {
        name: '编辑',
        callback: (data: any, row: any, index: number): void => {
          const treeData = computeTreeData(data, row, (item: any) => item.menuType !== 0);
          currentItem.value = row;
          currentItem.value.treeData = treeData.data;

          if (row.menuType !== 2) {
            columns.value[3].readOnly = false;
            columns.value[3].options = getMenuTypeOptions(true);
          } else {
            columns.value[3].readOnly = true;
            columns.value[3].options = getMenuTypeOptions(false);
          }

          handleMenuTypeChanged(columns.value, row.menuType);

          refEditDlg.value?.editUpdate('编辑菜单', row);
        }
      },
      {
        name: '删除',
        type: 'confirm',
        confirm: async (data: any, row: any, index: number) => {
          if (row.children && row.children.length != 0) {
            showInfo('请先删除菜单子菜单！');
          } else {
            const result = await doDeleteAsset(getTargetId(), row);
            if (result.code === 0) {
              msgInfo('删除菜单成功！');
              refresh();
            } else {
              msgError(result.message ? result.message : '删除菜单失败！');
            }
          }
        },
        cancel: (data: any, row: any, index: number) => {

        }
      }
    ]
  }
]);

const addMenu = () => {
  currentItem.value = newMenu();
  columns.value[3].readOnly = false;
  columns.value[3].options = getMenuTypeOptions(true);

  handleMenuTypeChanged(columns.value, currentItem.value.menuType);

  refEditDlg.value?.editAdd('新增菜单', currentItem.value);
}

defineExpose({
  refresh,
})

</script>

<style scoped>
.el-form-item-class .el-form-item__label {
  font-size: 12px;
}

</style>
